package com.chengyu.core.controller.callback;

import com.alibaba.fastjson.JSONObject;
import com.chengyu.core.controller.UserBaseController;
import com.chengyu.core.controller.callback.manager.CallbackManager;
import com.chengyu.core.domain.CommonConstant;
import com.chengyu.core.entity.CommonResult;
import com.chengyu.core.model.SysWeixinConfig;
import com.chengyu.core.util.weixin.WechatUtil;
import com.chengyu.core.util.weixin.WeixinResponse;
import com.chengyu.core.utils.StringUtils;
import com.chengyu.core.utils.WechatAesUtil;
import com.wechat.pay.contrib.apache.httpclient.auth.*;

import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * @类描述   	支付回调
 * @作者   		LeGreen
 * @创建时间  	2020年3月21日
 * @版本   		1.00
 * @修改记录
 * <pre>
 *     版本          修改人    		修改日期 			修改内容描述
 *     -----------------------------------------------------------
 *     1.00   	LeGreen    	2020年3月21日
 *     -----------------------------------------------------------
 * </pre>
 */
@Controller
public class PayCallbackController extends UserBaseController {

	private Logger logger = LoggerFactory.getLogger(PayCallbackController.class);

	@Autowired
	private CallbackManager paySusManager;

	private CertificatesVerifier verifier;



	private String apiclientKey = "/www/wwwroot/ccchongya.com/wxpay/apiclient_key.pem";


	private String wechatPaySerial = "4AF8EF44563B5889AE7F4351BAFFBC4E030AFE1E";

	private String apiV3Key="zoILFM69fxQ5YSUnq3H2hHSW0jDKgNQv";



	public CommonResult<String> paySusForZfb(HttpServletRequest request, HttpServletResponse response, String type) throws Exception{
		//1.从支付宝回调的request域中取值
		//获取支付宝返回的参数集合
		Map<String, String[]> aliParams = request.getParameterMap();
		//用以存放转化后的参数集合
		Map<String, String> conversionParams = new HashMap<String, String>();
		for (Iterator<String> iter = aliParams.keySet().iterator(); iter.hasNext();) {
			String key = iter.next();
			String[] values = aliParams.get(key);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "uft-8");
			conversionParams.put(key, valueStr);
		}
		System.out.println("支付宝支付回调:"+conversionParams);

//	    boolean flag = payService.checkPayNotify(conversionParams, PayService.PAY_TYPE_ALI);
		String tradeStatus = conversionParams.get("trade_status");// 获取交易状态
		String outTradeNo = conversionParams.get("out_trade_no");//获取商户之前传给支付宝的订单号（商户系统的唯一订单号）

		if(tradeStatus.equals("TRADE_SUCCESS")) {
			//只处理支付成功的订单: 修改交易表状态,支付成功
			paySusManager.getPaySusFactory(type).paySus(outTradeNo);

			String resStr = "success";
			BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
			out.write(resStr.getBytes());
			out.flush();
			out.close();
		}
		return CommonResult.success(null);
	}


//	//把json转成JavaBean(user对象)
//	public void test06() throws IOException {
//		String jsonStr = "{\"id\":1,\"username\":\"zs\",\"password\":\"123456\",\"email\":\"zs@163.com\",\"phone\":\"1386789898\"}";
//		//1.调用JSON.parseObject(String json,Class clazz);
//		//转换成user
//		User user = JSON.parseObject(jsonStr, User.class);
//		System.out.println(user);
//
//		//转换成map
//		Map map = JSON.parseObject(jsonStr, Map.class);
//		System.out.println(map);
//	}





	public CommonResult<String> paySusForWx(HttpServletRequest request, String type) throws Exception{


		//获取报文
		String body = getRequestBody(request);
		//随机串
		String nonceStr = request.getHeader("Wechatpay-Nonce");
		//微信传递过来的签名
		String signature = request.getHeader("Wechatpay-Signature");
		//证书序列号（微信平台）
		String serialNo = request.getHeader("Wechatpay-Serial");
		//时间戳
		String timestamp = request.getHeader("Wechatpay-Timestamp");
		//应答时间戳\n
		//应答随机串\n
		//应答报文主体\n
		String signStr = Stream.of(timestamp, nonceStr, body).collect(Collectors.joining("\n", "", "\n"));
		Map<String, String> map = new HashMap<>(2);
		try {
			String plainBody = decryptBody(body);
			logger.info("解密后的明文:{}",plainBody);

			logger.info("serialNo:{}",serialNo);
			logger.info("signStr:{}",signStr);
			logger.info("signature:{}",signature);


//			String nonce = request.getHeader("Wechatpay-Nonce");
//			//微信传递过来的签名
//			String signature = request.getHeader("Wechatpay-Signature");
//			//证书序列号（微信平台）
//			String wechatPaySerial = request.getHeader("Wechatpay-Serial");
//			//时间戳
//			String timestamp = request.getHeader("Wechatpay-Timestamp");
			// 验签
			NotificationRequest notificationRequest = new NotificationRequest.Builder()
					.withSerialNumber(serialNo)
					.withNonce(nonceStr)
					.withTimestamp(timestamp)
					.withSignature(signature)
					.withBody(body)
					.build();
			NotificationHandler handler = new NotificationHandler(verifier(), apiV3Key.getBytes(StandardCharsets.UTF_8));
			// 验签和解析请求体
			Notification notification = handler.parse(notificationRequest);


			//验证签名是否通过
//			boolean result = verifiedSign(serialNo, signStr, signature);
			boolean  result = true;
			if(result){
				//解密数据
				plainBody = decryptBody(body);
				logger.info("解密后的明文:{}",plainBody);

				Map<String, String> paramsMap = convertWechatPayMsgToMap(plainBody);
				//处理业务逻辑 TODO

				if(StringUtils.isNotBlank((String) paramsMap.get("trade_state")) && CommonConstant.SUCCESS.equals(paramsMap.get("trade_state"))){
					//支付成功
					paySusManager.getPaySusFactory(type).paySus((String) paramsMap.get("out_trade_no"));
				}

				//响应微信
//				map.put("code", "SUCCESS");
//				map.put("message", "成功");
				return CommonResult.success(paramsMap.get("trade_state"));


			}



		} catch (Exception e) {
			logger.error("微信支付回调异常:{}", e);
		}




		return CommonResult.success(null);
//		InputStream inStream = request.getInputStream();
//		int _buffer_size = 1024;
//		if (inStream != null) {
//			ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//			byte[] tempBytes = new byte[_buffer_size];
//			int count = -1;
//			while ((count = inStream.read(tempBytes, 0, _buffer_size)) != -1) {
//				outStream.write(tempBytes, 0, count);
//			}
//			tempBytes = null; outStream.flush();
//			//将流转换成字符串
//			String result = new String(outStream.toByteArray(), "UTF-8");
//			System.out.println("微信支付回调:"+result);
//			System.out.println("微信支付回调数据类型:"+		result.getClass().getName());
//			WeixinResponse response = JSON.parseObject(result, WeixinResponse.class);
//
//			//拿到请求头里的resource部分
//			JSONObject resources = JSONObject.parseObject(result).getJSONObject("resource");
//
//			System.out.println("resource:"+resources);
//			//用32位的v3密钥做个构造
//			String key = "zoILFM69fxQ5YSUnq3H2hHSW0jDKgNQv";
//			WechatAesUtil aesUtil = new WechatAesUtil(key.getBytes(StandardCharsets.UTF_8));
//			//取出resource下 associated_data nonce参数，再；配上v3key 用作解密ciphertext
//			byte[] associatedDataByte       =resources.getString("associated_data").getBytes(StandardCharsets.UTF_8);
//			byte[] nonceByte = resources.getString("nonce").getBytes(StandardCharsets.UTF_8);
//			String ciphertext = resources.getString("ciphertext");
//
//
//			//解密
//			String res = aesUtil.decryptToString(associatedDataByte,nonceByte,ciphertext);
//			JSONObject jsonObject = JSONObject.parseObject(res);
//			System.err.println("回调结果:"+jsonObject);
//
//			System.err.println("回调结果res:"+res);
//			if(CommonConstant.SUCCESS.equals(jsonObject.get("trade_state"))){
//
//			}
//
////			WeixinResponse response = WechatUtil.xmlToBean(result, WeixinResponse.class);
//
////			微信支付回调:{"id":"76ff088a-bc9a-5796-a5d7-330b8b70be48","create_time":"2024-03-24T10:48:19+08:00","resource_type":"encrypt-resource","event_type":"TRANSACTION.SUCCESS","summary":"支付成功","resource":{"original_type":"transaction","algorithm":"AEAD_AES_256_GCM","ciphertext":"s6ajK74LNJNXWys0KY3NFAG8bKYTrJpo4dYhDXnjpidx3QxumKGnzzHHCttHgZ55GTBT4JPNlv9itpwy6z0SrCcFV+mjjcJ1xb4NBDc8gbEOFPucJsAPzA0xf6p2twcV5e96LPvt61rgcYjBfbqFCTZOluEQvP0xLoUb1RRj9Db/kjGRui7ORKqdxjeUQCbvD5NZuKYtf10+s316VKf+5/y5bpv4wy6B4utZe4bua3UNdkp2bRBTVpHpQDGeZrYTUH2QTmRJaH48dRyC8lgyzcfMK3A+TOEMKkygBkQ9eG90iujLIF6OZBeYcdh1KQJTlg+IkEKwSJn1J2JdLgKiVQDYJ1AvndmJdB+niBPKsW5fZhP2wQmNDSJ0DiJfJcv4HazVJt6N/Z/COoSafRfuN3FBNrnlG1x4g5ZD9MII1sOJnBI01rGhgcj1SfFafXt3upkBeVlCZyoA73HNcHIjqxE2TAFDN07SN94NKDYL92uCIUPA4JAf7K57UfwoAloilKSgM2vpamaW1wyUzvk2uLEpejgx2ostDpWjDrm5tB7P67Ts5dXY8/JGq9DnVzWQiH4=","associated_data":"transaction","nonce":"AhnCpFLP0oiL"}}
////			jsonObject.get("trade_state")
//			//通知成功
//			if(StringUtils.isNotBlank((String) jsonObject.get("trade_state")) && CommonConstant.SUCCESS.equals(jsonObject.get("trade_state"))){
//					//支付成功
//					paySusManager.getPaySusFactory(type).paySus((String) jsonObject.get("out_trade_no"));
//			}
//
//
//
//		}
//
//		return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
	}



	/**
	 * 解密body的密文
	 *
	 * "resource": {
	 *         "original_type": "transaction",
	 *         "algorithm": "AEAD_AES_256_GCM",
	 *         "ciphertext": "",
	 *         "associated_data": "",
	 *         "nonce": ""
	 *     }
	 *
	 * @param body
	 * @return
	 */
//	@SneakyThrows
	private String decryptBody(String body) throws IOException, GeneralSecurityException {


		WechatAesUtil aesUtil = new WechatAesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
//		WechatAesUtil aesUtil = new WechatAesUtil(wechatPayConfig.getApiV3Key().getBytes("utf-8"));

		JSONObject object = JSONObject.parseObject(body);
		JSONObject resource = object.getJSONObject("resource");
		String ciphertext = resource.getString("ciphertext");
		String associatedData = resource.getString("associated_data");
		String nonce = resource.getString("nonce");


		return aesUtil.decryptToString(associatedData.getBytes("utf-8"),nonce.getBytes("utf-8"),ciphertext);

	}

	/**
	 * 转换body为map
	 * @param plainBody
	 * @return
	 */
	private Map<String,String> convertWechatPayMsgToMap(String plainBody){

		Map<String,String> paramsMap = new HashMap<>(2);

		JSONObject jsonObject = JSONObject.parseObject(plainBody);

		//商户订单号
		paramsMap.put("out_trade_no",jsonObject.getString("out_trade_no"));

		//交易状态
		paramsMap.put("trade_state",jsonObject.getString("trade_state"));

		//附加数据
//		paramsMap.put("account_no",jsonObject.getJSONObject("attach").getString("accountNo"));

		return paramsMap;

	}




	/**
	 * 验证签名
	 *
	 * @param serialNo  微信平台-证书序列号
	 * @param signStr   自己组装的签名串
	 * @param signature 微信返回的签名
	 * @return
	 * @throws UnsupportedEncodingException
	 */
//	private boolean verifiedSign(String serialNo, String signStr, String signature) throws UnsupportedEncodingException {
//
//
//		return verifier.verify(serialNo, signStr.getBytes("utf-8"), signature);
//	}


	/**
	 * 读取请求数据流
	 *
	 * @param request
	 * @return
	 */
	private String getRequestBody(HttpServletRequest request) {

		StringBuffer sb = new StringBuffer();

		try (ServletInputStream inputStream = request.getInputStream();
			 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
		) {
			String line;

			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}

		} catch (IOException e) {
			logger.error("读取数据流异常:{}", e);
		}

		return sb.toString();

	}

	/**
	 * 获得验签器
	 * @return
	 * @throws Exception
	 */
	public Verifier verifier() throws Exception {
		SysWeixinConfig config = WechatUtil.config;
		//获取证书管理器实例
		CertificatesManager certificatesManager = CertificatesManager.getInstance();
		certificatesManager.putMerchant(config.getMchId(), new WechatPay2Credentials(config.getMchId(),new PrivateKeySigner(wechatPaySerial, getPrivateKey())), apiV3Key.getBytes(StandardCharsets.UTF_8));
		// 从证书管理器中获取verifier
		Verifier verifier = certificatesManager.getVerifier(config.getMchId());
		return verifier;
	}


	/**
	 * 获取商户证书私钥
	 *
	 * @return 私钥对象
	 */
	public PrivateKey getPrivateKey() throws IOException {
		SysWeixinConfig config = WechatUtil.config;
		PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(apiclientKey));
		return merchantPrivateKey;
	}


}